package text;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.StringTokenizer;
import settings.*;

public class ReadTextFile
{

    /**
     * Returns an arraylist of strings for the names of the files
     * 
     * @param file
     *            File path
     * @param numLinks
     *            Number of links
     * @return
     */
    public static ArrayList<String> titles_to_list(String file, int numLinks)
    {
	// allocate memory for list
	ArrayList<String> titleArrayList = new ArrayList<String>(numLinks);
	int count = 0;

	// read in the file
	try
	{
	    // objects need
	    FileInputStream fstream = new FileInputStream(file);
	    DataInputStream in = new DataInputStream(fstream);
	    BufferedReader br = new BufferedReader(new InputStreamReader(in));
	    String strLine;

	    titleArrayList.add(" ");// placeholder for position 0

	    // Read File Line By Line
	    while ((strLine = br.readLine()) != null)
	    {// get line
		titleArrayList.add(strLine);
		// Testing - Shows the text file as it is read in
		// System.out.println(strLine);
		// System.out.println(++count);
	    }
	    in.close();// Close the input stream
	} catch (Exception e)
	{// Catch exception if any
	    System.err.println("Error: " + e.getMessage());
	    return null;
	}
	return titleArrayList;
    }

    public static ArrayList<Integer> readStartingNumbers()
    {
	ArrayList<Integer> al = new ArrayList<Integer>();

	try
	{
	    // objects need
	    FileInputStream fstream = new FileInputStream(Global.startFileLocation);
	    DataInputStream in = new DataInputStream(fstream);
	    BufferedReader br = new BufferedReader(new InputStreamReader(in));
	    String strLine;

	    // Read File Line By Line
	    while ((strLine = br.readLine()) != null)
	    {// get line
		al.add(Integer.parseInt(strLine));
	    }
	    in.close();// Close the input stream
	} catch (Exception e)
	{// Catch exception if any
	    System.err.println("Error: " + e.getMessage());
	    return null;
	}
	// TODO
	return al;
    }

    // given ArrayList<String>, write out to a file
    protected static void al_writeToFile(String filename, ArrayList<String> als) throws IOException
    {
	// Code used from: http://j.mp/Ix33U4
	File f = new File(filename);
	// System.out.println(filename);
	f.createNewFile();
	FileWriter file = new FileWriter(f);
	PrintWriter out = new PrintWriter(file);

	// create output
	String text = "";
	for (int i = 0; i < als.size(); i++)
	{
	    text = text + als.get(i);
	    if (i != als.size() - 1)
		text = text + "\n";
	}
	// write
	out.write(text);
	out.close();
    }

    // Since there are too many links in the file, this code will break the huge file into smaller files for almost random access
    public static ArrayList<Integer> bigFile_smallFile(String file, String directory)
    {
	int count = 1;// goes to one in while loop
	// allocate memory for Adjacency list
	ArrayList<String> smallerFile = new ArrayList<String>(Global.numPagesPerFile);
	ArrayList<Integer> fileStartValues = new ArrayList<Integer>();

	// read in the file
	try
	{
	    // objects need
	    FileInputStream fstream = new FileInputStream(file);
	    DataInputStream in = new DataInputStream(fstream);
	    BufferedReader br = new BufferedReader(new InputStreamReader(in));
	    StringTokenizer st;
	    String strLine, token;
	    int pageStart;
	    boolean addValue = true;

	    // Read File Line By Line
	    while ((strLine = br.readLine()) != null)
	    {// get line
		count++;

		// add to the list of file start numbers
		if (addValue)
		{
		    st = new StringTokenizer(strLine, ": ");
		    token = st.nextToken(); // get pageNumber
		    pageStart = Integer.parseInt(token);
		    fileStartValues.add(pageStart);// insert into the list
		    addValue = false;
		}

		smallerFile.add(strLine);// add
		if (count % Global.numPagesPerFile == 0)
		{// full, so write out to file
		    addValue = true;
		    // write to file and other stuff
		    al_writeToFile(Global.smallFileLocation + fileStartValues.get(fileStartValues.size() - 1) + ".txt", smallerFile);
		    // new memory
		    smallerFile = new ArrayList<String>(Global.numPagesPerFile);
		}
	    }

	    // write the startingValues to memory
	    ArrayList<String> finalconvert = new ArrayList<String>();
	    for (int i = 0; i < fileStartValues.size(); i++)
	    {
		// System.out.println(fileStartValues.get(i));
		finalconvert.add(Integer.toString(fileStartValues.get(i)));
	    }
	    // System.out.println("Here1");
	    al_writeToFile(Global.startFileLocation, finalconvert);
	    // System.out.println("Here2");

	    in.close();// Close the input stream
	    return fileStartValues;
	} catch (Exception e)
	{// Catch exception if any
	    System.err.println("Error: " + e.getMessage());
	    return null;
	}
    }

    // same as the other links_to_graph but uses different data structures
    public static LinkedList<Integer>[] links_to_graph(String file, int numLinks, boolean nothing)
    {
	// allocate memory for Adjacency list
	LinkedList<Integer>[] adjacencylistgraph = new LinkedList[numLinks];
	int count = 0;

	// read in the file
	try
	{
	    // objects need
	    FileInputStream fstream = new FileInputStream(file);
	    DataInputStream in = new DataInputStream(fstream);
	    BufferedReader br = new BufferedReader(new InputStreamReader(in));
	    StringTokenizer st;
	    String strLine;
	    LinkedList<Integer> outgoingLinks;

	    adjacencylistgraph[0] = new LinkedList<Integer>();// placeholder for position 0

	    // Read File Line By Line
	    while ((strLine = br.readLine()) != null)
	    {// get line
		st = new StringTokenizer(strLine, " :"); // tokenize
		// Testing - Shows the text file as it is read in
		// System.out.println(strLine);

		// the outgoing links (easier to use this)
		outgoingLinks = new LinkedList<Integer>();

		while (st.hasMoreElements())
		{
		    outgoingLinks.add(Integer.parseInt(st.nextToken()));// get next token //parse it //add to adjacency list
		}

		// add this outgoing link arraylist to the big page graph
		adjacencylistgraph[++count] = outgoingLinks; // add to the end in the correct position that corresponds with its pageNum
		if (count % 1000 == 0)
		    System.out.println(count);
	    }
	    in.close();// Close the input stream
	} catch (Exception e)
	{// Catch exception if any
	    System.err.println("Error: " + e.getMessage());
	    return null;
	}

	// Testing to show the values in the adjacencylistgraph
	// for(int i=0;i<adjacencylistgraph.size();i++)
	// for(int j=0;j<adjacencylistgraph.get(i).size();j++)
	// System.out.println(i + " " + adjacencylistgraph.get(i).get(j));

	return adjacencylistgraph;
    }

    // Input: txt file of outgoing links
    // Output: AL<AL<int>> Adjacency list
    public static ArrayList<ArrayList<Integer>> links_to_graph(String file)
    {
	// allocate memory for Adjacency list
	ArrayList<ArrayList<Integer>> adjacencylistgraph = new ArrayList<ArrayList<Integer>>();

	// read in the file
	try
	{
	    // objects need
	    FileInputStream fstream = new FileInputStream(file);
	    DataInputStream in = new DataInputStream(fstream);
	    BufferedReader br = new BufferedReader(new InputStreamReader(in));
	    StringTokenizer st;
	    String strLine;
	    ArrayList<Integer> outgoingLinks;

	    adjacencylistgraph.add(new ArrayList<Integer>(1));// placeholder for position 0

	    // Read File Line By Line
	    while ((strLine = br.readLine()) != null)
	    {// get line
		st = new StringTokenizer(strLine, " :"); // tokenize
		// Testing - Shows the text file as it is read in
		// System.out.println(strLine);

		// the outgoing links
		outgoingLinks = new ArrayList<Integer>();

		while (st.hasMoreElements())
		{
		    outgoingLinks.add(Integer.parseInt(st.nextToken()));// get next token //parse it //add to adjacency list
		}

		// add this outgoing link arraylist to the big page graph
		adjacencylistgraph.add(outgoingLinks); // add to the end in the correct position that corresponds with its pageNum
	    }
	    in.close();// Close the input stream
	} catch (Exception e)
	{// Catch exception if any
	    System.err.println("Error: " + e.getMessage());
	    return null;
	}

	// Testing to show the values in the adjacencylistgraph
	// for(int i=0;i<adjacencylistgraph.size();i++)
	// for(int j=0;j<adjacencylistgraph.get(i).size();j++)
	// System.out.println(i + " " + adjacencylistgraph.get(i).get(j));

	return adjacencylistgraph;
    }

}
